import { MciButton, MciNotification, MciSvgIcon } from '@/components/base';
import { NODE_LIST, NODE_TYPE } from '@/constants/config';
import { useGraph } from '@/hooks/useGraph';
import { useNodeResults } from '@/store/node-results';
import { useNodeVerification } from '@/store/node-verification';
import { fetchOfSSE } from '@/utils/fetch';
import { showNodeStatusWithState } from '@/utils/graph';
import { PropType } from 'vue';
import { NodeLogger } from './components/NodeLogger';
import { NodeVerificationLogger } from './components/NodeVerificationLogger';
import { NodeOfCreateBtn } from './components/NodeOfCreateBtn';
import { baseNodeProps } from './define';
import './index.scss';
import { activeNodeId } from './state';

const baseNodeContentProps = {
  nodeName: {
    type: String,
    default: ''
  },
  icon: {
    type: String,
    default: ''
  },
  nodeType: {
    type: String as PropType<keyof typeof NODE_TYPE>,
    default: ''
  }
};

export const BaseNodeContent = defineComponent({
  props: {
    ...baseNodeContentProps,
    nodeNameEditable: {
      type: Boolean,
      default: false
    }
  },
  setup(props, { slots }) {
    const node = computed(() => {
      return NODE_LIST[props.nodeType] || {};
    });

    const nodeName = computed(() => {
      return props.nodeName || node.value.nodeName;
    });

    return () => {
      return (
        <div class="flex items-center base-node-content">
          <MciSvgIcon name={node.value.icon || props.icon} width={18} class="ml-8" color="var(--color-grey-4)" />
          <span class="label ml-8">{nodeName.value}</span>
          {slots.default?.()}
        </div>
      );
    };
  }
});

export const BaseNode = defineComponent({
  props: {
    ...baseNodeProps,
    ...baseNodeContentProps
  },
  setup(props, { slots }) {
    const { graph, interactingState } = useGraph();
    const execResultsStore = useNodeResults();
    const verificationStore = useNodeVerification();
    const isFocus = computed(() => activeNodeId.value === props.node?.id);
    const updateDataRef = ref({} as Record<string, any>);
    let targetEl: HTMLElement | null = null;
    let position = '';
    let isCancelClick = false;
    const approveLoading = ref(false);

    const finalData = computed(() => {
      const { node, data } = props;
      const graphData = node?.getData();
      const finalData = graphData || data || props || {};
      return Object.assign({}, finalData, updateDataRef.value, { node });
    });

    const getPosition = () => {
      const rect = targetEl?.getBoundingClientRect() || { x: 0, y: 0 };
      return [rect.x, rect.y].join('-');
    };

    const onMouseup = () => {
      isCancelClick = false;
      if (position !== getPosition()) {
        isCancelClick = true;
      }
    };

    const onMousedown = (e: MouseEvent) => {
      targetEl = e.target as HTMLElement;
      position = getPosition();
    };

    const approve = (status: 'pass' | 'reject') => {
      const nodeResult = execResultsStore.resultsOfList.find((item) => item.nodeId === props.node?.id);
      if (!nodeResult) {
        MciNotification.warning({ message: '未找到节点执行结果' });
        return;
      }
      approveLoading.value = true;
      fetchOfSSE('/decision-flow/manualCallbackSse', {
        method: 'POST',
        body: JSON.stringify({
          flowId: nodeResult.flowId!,
          nodeId: nodeResult.nodeId!,
          status: status === 'pass' ? 1 : -1,
          execId: nodeResult.execId!,
          parentId: nodeResult.parentId!
        }),
        headers: {
          'Content-Type': 'application/json'
        },
        onMessage(message) {
          if (message === '[DONE]') {
            approveLoading.value = false;
            MciNotification.success({
              message: '操作成功',
              position: 'bottom-right'
            });
          }
          try {
            graph.value?.getNodes().map((node) => {
              const hasResult = execResultsStore.resultsOfList.some((item) => {
                return item.nodeId === node.id;
              });

              if (!hasResult) {
                node.getData().setNodeData({
                  status: ''
                });
              }
            });

            graph.value?.getEdges().map((edge) => {
              const hasResult = execResultsStore.resultsOfList.some((item) => {
                return item.lineId === edge.id;
              });

              if (!hasResult) {
                edge.attr({
                  line: {
                    stroke: '#A2B1C3',
                    strokeDasharray: 0,
                    strokeWidth: 1.1,
                    style: {
                      animation: ''
                    }
                  }
                });
              }
            });
            const data = JSON.parse(message);
            if (data) {
              execResultsStore.addResults(data);
              showNodeStatusWithState(graph.value!, data);
            }
          } catch (error) {}
        }
      });
    };

    onMounted(() => {
      if (props.node) {
        // https://x6.antv.antgroup.com/tutorial/intermediate/vue
        // 因为setNode不会触发组件更新, 所以通过回调函数触发响应式属性触发组件更新
        props.node.setData({
          setNodeData(data: Record<string, any>) {
            updateDataRef.value = data;
          }
        });
      }
    });

    return () => {
      const { status = 'DEFAULT' } = finalData.value;
      return (
        <div
          style={{
            background: status === 'REJECT' ? 'var(--color-red-1)' : status === 'PASS'? '#e7f2dd' : 'white',
            borderColor: status === 'REJECT' ? 'var(--color-red-5)' : status === 'PASS'? '#52c41a' : '#c2c8d5',
            borderLeftColor: status === 'REJECT' ? 'var(--color-red-5)' : status === 'PASS'? '#52c41a' : '#5f95ff',
            flexGrow: '1',
            minWidth: '161px', /* 最小宽度 */
            maxWidth: '180px', /* 最大宽度 */
          }}
          class={['node relative', status.toLowerCase(), isFocus.value ? 'is-focus' : '']}
          onClick={(e) => {
            if (isCancelClick) {
              return;
            }
            if (isFocus.value) {
              e.stopPropagation();
            }
            props.onClick?.(e);
            activeNodeId.value = props.node?.id;
          }}
          onMouseup={onMouseup}
          onMousedown={(e) => {
            props.onMousedown?.(e, { ...finalData.value });
            onMousedown(e);
          }}>
          <div class="flex items-center">
            {slots.default?.() || <BaseNodeContent nodeName={finalData.value.nodeName} nodeType={finalData.value.nodeType} />}
          </div>
          {props.isFromNodeList === false && (
            <>
              <span class="status">
                {status === 'PASS' && <MciSvgIcon name="node-state--success" color="#52c41a" />}
                {status === 'REJECT' && <MciSvgIcon name="node-state--error" color="#f00" />}
                {['RUNNING', 'WAITING'].includes(status) && <MciSvgIcon name="node-state--running" color="var(--color-grey-5)" />}
              </span>
              {interactingState.value && !execResultsStore.hasExecResult && (
                <NodeOfCreateBtn {...finalData.value} node={finalData.value.node} />
              )}
            </>
          )}

          {execResultsStore.hasExecResult && (
            <>
              {status === 'WAITING' ? (
                <div
                  onClick={(e) => e.stopPropagation()}
                  class="manual-confirm flex flex-col gap-8 absolute top-48 left-[50%] -translate-x-[50%] w-200 p-12 bg-white rounded-8">
                  <h3 class="text-center text-value-16_bold">人工审核确认</h3>

                  <div class="flex justify-center pt-12">
                    <MciButton loading={approveLoading.value} onClick={() => approve('reject')} type="danger">
                      拒绝
                    </MciButton>
                    <MciButton loading={approveLoading.value} onClick={() => approve('pass')} type="primary">
                      通过
                    </MciButton>
                  </div>
                </div>
              ) : (
                <NodeLogger nodeId={props.node?.id} />
              )}
            </>
          )}

          {verificationStore.hasExecResult && (
            <>
              <NodeVerificationLogger nodeId={props.node?.id} />
            </>
          )}
        </div>
      );
    };
  }
});
